package game;

import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import lion.ann.MsgCodeAnn;
import lion.codec.IServerDispatcher;
import lion.core.GamePlayer;
import lion.core.SpringContextHolder;
import lion.message.MsgDispatcher;
import lion.message.MyRequestMsg;
import lion.netty.NettyServer;
import lion.processor.MsgProcessor;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 主要启动的类
 * 
 * @author hexuhui
 * 
 */
public class GameServer implements IServerDispatcher {

	private static Logger logger = LoggerFactory.getLogger(GameServer.class);

	private NettyServer amf3Server;

	private AbstractApplicationContext ctx;

	public static MsgDispatcher msgDispatcher = new MsgDispatcher();

	private static GameServer instance;

	/**
	 * 单线程执行所有任务
	 */
	private ExecutorService threadPool;

	public GameServer(AbstractApplicationContext ctx) {
		this.ctx = ctx;
		amf3Server = new NettyServer(this);
		amf3Server.initServer();
		amf3Server.startServer(8653);
		addShutDownHook();
		instance = this;
		initThreadPool();
	}

	private void initThreadPool() {
		BasicThreadFactory factory = new BasicThreadFactory.Builder().namingPattern("logic-thread").daemon(true).priority(Thread.MAX_PRIORITY).build();
		threadPool = Executors.newSingleThreadExecutor(factory);
	}

	public static GameServer getInstance() {
		return instance;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AbstractApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
		GameServer server = new GameServer(factory);
		logger.info("server init success!,factory={},server={}", factory, server);
		server.onStart();
	}

	private void addShutDownHook() {
		Runtime.getRuntime().addShutdownHook(new Thread("shutdownHook-thread") {
			public void run() {
				logger.warn("shuting down amf3 server");
				amf3Server.stop();
				onStop();
			}
		});
	}

	public void stopGameLogic() {
		kickAllPlayer();
		threadPool.shutdown();
		try {
			threadPool.awaitTermination(600, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
	}

	protected void onStop() {
		// in game process
		logger.warn("closeing spring context!");
		ctx.close();
	}

	private long kickAllPlayer() {
		long ret = 0;
		// 为了保存运行的过程中，不被改变
		// ArrayList<Hero> copy = new ArrayList<Hero>(onlineManager.getCharacterList());
		// final CountDownLatch cdl = new CountDownLatch(copy.size());
		// for (Hero c : copy) {
		// c.getDownLineManager().downLine(new Runnable() {
		// @Override
		// public void run() {
		// cdl.countDown();
		// }
		// });
		// }
		// try {
		// cdl.await(3, TimeUnit.MINUTES);
		// ret = cdl.getCount();
		// } catch (InterruptedException e) {
		// logger.error(e.getMessage(), e);
		// }
		return ret;
	}

	protected void onStart() {
		// frameUpdataService = new FrameUpdateService(this);
		// frameUpdataService.startFrameupdate();
		// 注册消息
		Collection<Object> annotatedBeans = SpringContextHolder.getBeanByAnnotation(MsgCodeAnn.class);
		for (Object obj : annotatedBeans) {
			MsgCodeAnn ann = obj.getClass().getAnnotation(MsgCodeAnn.class);
			msgDispatcher.addMsgProcessor(ann.msgcode(), (MsgProcessor) obj);
		}
	}

	/**
	 * 处理io请求
	 * 
	 * @param player
	 * @param requestMsg
	 */
	public void syncExecuteIoRequest(final GamePlayer player, final MyRequestMsg requestMsg) {
		threadPool.execute(new Runnable() {
			@Override
			public void run() {
				try {
					int msgCode = requestMsg.getMsgCode();
					MsgProcessor processor = msgDispatcher.getMsgProcessor(msgCode);
					if (processor == null) {
						logger.warn("coult not find processer for={}", msgCode);
						return;
					}
					if (!processor.isEnable()) {
						logger.warn("msg processor has been closed code={}", msgCode);
						return;
					}
					processor.process(player, requestMsg);
				} catch (Exception e) {
					logger.error("logic pool execute error!", e);
				}
			}
		});
	}

	/**
	 * 执行其他任务
	 * 
	 * @param job
	 */
	public void syncExecuteJob(Runnable job) {
		threadPool.execute(job);
	}

	@Override
	public MsgDispatcher getMsgDispatcher() {
		return null;
	}

	@Override
	public String getWorkPath() {
		return null;
	}

	@Override
	public String getProccessProp() {
		return null;
	}

	@Override
	public boolean checkIP(String ip) {
		// TODO check ip
		return true;
	}

	@Override
	public MsgProcessor getMsgProcessor(int msgCode) {
		return msgDispatcher.getMsgProcessor(msgCode);
	}

	@Override
	public void sessionClosed(GamePlayer player) {

	}
}
